package org.oschina.util;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.SolrQuery.ORDER;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrInputDocument;

public class SolrUtil {

	/**
	 * 查询
	 * @param <T>
	 * @param server
	 * @param where
	 * @param sort
	 * @param order
	 * @param first
	 * @param max
	 * @param type
	 * @param totalHits 索引0代表匹配的总数
	 * @return
	 * @throws SolrServerException
	 * @throws InvocationTargetException 
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 */
	public static <T>List<T> query(HttpSolrServer server,String where,String sort[],String order[],int first,int max,Class<T> type,Integer totalHits[]) throws SolrServerException, IllegalAccessException, InvocationTargetException, InstantiationException
	{
		QueryResponse queryResponse=getQueryResponse(server,getQuery(where,sort,order,first,max));
		SolrDocumentList documentList=queryResponse.getResults();
		if(totalHits!=null)
			totalHits[0]=(int) documentList.getNumFound();

		//封装结果
		List<T> result=new ArrayList<T>();
		for(SolrDocument document:documentList)
		{
			Map<String,Object> values=document.getFieldValueMap();
			Set<String> keys=values.keySet();
			Object instace=type.newInstance();
			for(String key:keys)
			{
				try
				{
					Field field=type.getDeclaredField(key);
					BeanUtils.setProperty(instace, key, ConvertUtils.convert(document.get(key), field.getType()));
				}
				catch(NoSuchFieldException e)
				{
					continue;
				}
			}
			result.add((T)instace);
		}
		
		return result;
	}
	
	/**
	 * 写入
	 * @param server
	 * @param fields
	 * @param values
	 * @throws IOException 
	 * @throws SolrServerException 
	 */
	public static void write(HttpSolrServer server,String fields[],Object values[]) throws SolrServerException, IOException
	{
		SolrInputDocument document=new SolrInputDocument();
		for(int i=0;i<fields.length;i++)
			document.addField(fields[i], values[i]);
		
		server.add(document);
		commit(server);
	}
	
	/**
	 * 更新
	 * @param server
	 * @param where
	 * @param fields
	 * @param values
	 * @throws SolrServerException 
	 * @throws IOException 
	 */
	public static void update(HttpSolrServer server,String where,String fields[],Object values[]) throws SolrServerException, IOException
	{
		QueryResponse queryResponse=getQueryResponse(server, getQuery(where, null, null, 0, 1));
		SolrDocumentList documentList=queryResponse.getResults();
		if(documentList==null || documentList.isEmpty())
			return;
		
		SolrDocument document=documentList.get(0);
		Map<String,Object> valueMap=document.getFieldValueMap();
		Set<String> keys=valueMap.keySet();
		SolrInputDocument inputDocument=new SolrInputDocument();
		
		for(String key:keys)
			inputDocument.addField(key, valueMap.get(key));
		
		for(int i=0;i<fields.length;i++)
		{
			if(valueMap.get(fields[i])!=null)
				inputDocument.setField(fields[i], values[i]);
			else
				inputDocument.addField(fields[i], values[i]);
		}
		
		server.add(inputDocument);
		commit(server);
	}
	
	/**
	 * 移除
	 * @param server
	 * @param where
	 * @throws IOException 
	 * @throws SolrServerException 
	 */
	public static void remove(HttpSolrServer server,String where) throws SolrServerException, IOException
	{
		server.deleteByQuery(where);
		commit(server);
	}
	
	/**
	 * 提交
	 * @param server
	 * @throws SolrServerException
	 * @throws IOException
	 */
	public static void commit(HttpSolrServer server) throws SolrServerException, IOException
	{
		server.optimize();
		server.commit();
	}
	
	/**
	 * 获得查询响应对象
	 * @param server
	 * @param solrQuery
	 * @return
	 * @throws SolrServerException
	 */
	private static QueryResponse getQueryResponse(HttpSolrServer server,SolrQuery solrQuery) throws SolrServerException
	{
		return server.query(solrQuery);
	}
	
	/**
	 * 返回查询对象
	 * @param where
	 * @param sort  desc 降序 asc 升序
	 * @param order
	 * @param first
	 * @param max
	 * @return
	 */
	private static SolrQuery getQuery(String where,String sort[],String order[],int first,int max)
	{
		SolrQuery solrQuery=new SolrQuery();
		solrQuery.setQuery(where);
		if(sort!=null && order!=null && sort.length!=0 && order.length!=0 && sort.length==order.length)
		{
			for(int i=0;i<sort.length;i++)
			{
				if("desc".equals(order[i]))
					solrQuery.addSort(sort[i], ORDER.desc);
				else if("asc".equals(order[i]))
					solrQuery.addSort(sort[i], ORDER.asc);
			}
		}
		solrQuery.setStart(first);
		solrQuery.setRows(max);
		return solrQuery;
	}
	
	/**
	 * 获得
	 * @param url
	 * @return
	 */
	public static HttpSolrServer getHttpSolrServer(String url)
	{
		return new HttpSolrServer(url);
	}
}